#include "TemporaryCodeGenerator.h"
#include <iostream>
#include <sstream>

TemporaryCodeGenerator::TemporaryCodeGenerator(const std::string &tmpCodeFile):
	destFile(tmpCodeFile.c_str())
{
	nextAddr = 0;
	op("jmp","****", "****", "L");
}
void TemporaryCodeGenerator::generateCode(void)
{
	for(int i=0; i<vTC.size(); i++) {
		destFile << vTC[i] << std::endl;
	}
}
void TemporaryCodeGenerator::op(const std::string &opStr,
		const std::string &resultAddr,
		const std::string &oplAddr,
		const std::string &oprAddr)
{
	std::ostringstream tc;
	tc << nextAddr++ << " : " << opStr << "  " << resultAddr << ", " << oplAddr <<", " << oprAddr;	
	vTC.push_back(tc.str());
	
}
void TemporaryCodeGenerator::op(const std::string &opStr,
		const std::string &resultAddr,
		int val)
{
	std::ostringstream tc;
	tc << nextAddr++ << " : " << opStr << "  " << resultAddr << ", " << val;	
	vTC.push_back(tc.str());
	
}

void TemporaryCodeGenerator::op(const std::string &opStr,
		const std::string &resultAddr,
		double val)
{
	std::ostringstream tc;
	tc << nextAddr++ << " : " << opStr << "  " << resultAddr << ", " << val;	
	vTC.push_back(tc.str());
	
}
void TemporaryCodeGenerator::intToFloat(const std::string &floatAddr,
		const std::string &intAddr)
{
	std::ostringstream tc;
	tc << nextAddr++ << " : int_to_float  " << floatAddr << ", " << intAddr <<", " << "****";	
	vTC.push_back(tc.str());
	
}
void TemporaryCodeGenerator::plus(const std::string &resultAddr,
		const std::string &oplAddr,  
		const std::string &oprAddr)
{
	std::ostringstream tc;
	tc << nextAddr++ << " : +  " << resultAddr << ", " << oplAddr <<", "
	       << oprAddr;	
	vTC.push_back(tc.str());

}
void TemporaryCodeGenerator::minus(const std::string &resultAddr,
		const std::string &oplAddr,  
		const std::string &oprAddr)
{
	std::ostringstream tc;
	tc << nextAddr++ << " : -  " << resultAddr << ", " << oplAddr <<", "
	       << oprAddr;	
	vTC.push_back(tc.str());
}

void TemporaryCodeGenerator::mul(const std::string &resultAddr,
		const std::string &oplAddr,  
		const std::string &oprAddr)
{
	std::ostringstream tc;
	tc << nextAddr++ << " : *  " << resultAddr << ", " << oplAddr <<", "
	       << oprAddr;	
	vTC.push_back(tc.str());
}
void TemporaryCodeGenerator::div(const std::string &resultAddr,
		const std::string &oplAddr,  
		const std::string &oprAddr)
{
	std::ostringstream tc;
	tc << nextAddr++ << " : /  " << resultAddr << ", " << oplAddr <<", "
	       << oprAddr;	
	vTC.push_back(tc.str());
}

void TemporaryCodeGenerator::assign(const std::string &destAddr,
		const std::string &srcAddr)
{
	std::ostringstream tc;
	tc << nextAddr++ << " : =  " << destAddr << ", " << srcAddr <<", "
	       << "****";	
	vTC.push_back(tc.str());
}
void TemporaryCodeGenerator::if_begin(const std::string &conExpValAddr)
{
	ifStack.push(nextAddr);
	op("jz","****", conExpValAddr, "L");
}

void TemporaryCodeGenerator::if_end(void)
{
	std::ostringstream lineStr;
	lineStr << nextAddr;
	vTC[ifStack.top()] += lineStr.str();
	ifStack.pop();
}
void TemporaryCodeGenerator::else_begin(void)
{
	std::ostringstream lineStr;
	op("jmp", "****", "****", "L");
	lineStr << nextAddr;
	vTC[ifStack.top()] += lineStr.str();
	ifStack.pop();
	ifStack.push(nextAddr-1);
}

void TemporaryCodeGenerator::if_else_end(void)
{
	if_end();
}

void TemporaryCodeGenerator::while_begin(void)
{
	//记录下while语句开始的位置
	whileStack.push(nextAddr);
}

void TemporaryCodeGenerator::while_condition(const std::string &conExpValAddr)
{
	//条件为假时，跳转到出口：
	op("jz","****", conExpValAddr, "L");
	//记录该位置：
	whileStack.push(nextAddr-1);
}

void TemporaryCodeGenerator::while_end(void)
{
	std::ostringstream lineStr;
	lineStr << nextAddr+1;
	vTC[whileStack.top()] += lineStr.str();
	whileStack.pop();
	lineStr.seekp(0);
	lineStr << "L" <<whileStack.top();
	whileStack.pop();
	//设置无条件转移指令：
	op("jmp", "****", "****",lineStr.str());
}

void TemporaryCodeGenerator::return_value(const std::string &retValAddr)
{
	op("ret", "****", retValAddr);
}

void TemporaryCodeGenerator::return_void(void)
{
	op("ret", "****", "****");
}
int TemporaryCodeGenerator::func_begin(void)
{
	return nextAddr;
}
int TemporaryCodeGenerator::main_begin(void)
{
	std::ostringstream lineStr;
	lineStr << nextAddr;
	vTC[0] += lineStr.str();
	return nextAddr;
}
void TemporaryCodeGenerator::func_end(void)
{
}
